package com.zealfi.example.test.rabbitmq.base;

import com.zealfi.example.test.rabbitmq.util.FastJsonMQMessageConvert;
import com.zealfi.example.test.rabbitmq.util.JsonTool;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;

import java.util.UUID;

/**
 * @功能:【MsgSendConfirmCallBack 继承RabbitTemplate.ConfirmCallback, 消息确认监听器】
 * @作者:代守诚
 * @日期:2018/10/19
 * @时间:17:44
 */
public abstract class MsgSendConfirmReturnsCallBack implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {

    private RabbitTemplate rabbitTemplate;

    public MsgSendConfirmReturnsCallBack(RabbitTemplate re) {
        System.out.println("**************开始加载********************");
        this.rabbitTemplate = re;
        this.rabbitTemplate.setConfirmCallback(this); //设置
        this.rabbitTemplate.setMessageConverter(new FastJsonMQMessageConvert());
        System.out.println("**************加载成功********************" + JsonTool.getJsonString(rabbitTemplate));
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack) {
            System.out.println("***********消息发送成功id**************" + correlationData.getId());
            changeStatus(correlationData.getId());//处理自己的业务逻辑
        } else {
            System.out.println("***********消息发送失败id**************" + correlationData.getId());
            //处理自己的业务逻辑,比如说开启重试机制(本系统根据自身的业务需求,在定时任务中统一处理)
        }
    }

    @Override
    public void returnedMessage(org.springframework.amqp.core.Message message, int replyCode, String replyText, String exchange, String routingKey) {
        System.err.println("*******收到回调*******");
        System.err.println("********return--message:" + new String(message.getBody()) + ",replyCode:" + replyCode + ",replyText:" + replyText + ",exchange:" + exchange + ",routingKey:" + routingKey + "********");
    }

    /**
     * 外部请求发送消息
     *
     * @param routingKey
     * @return
     */
    public boolean sendMsg(String routingKey, Object msg) {
        Message message = new Message(null, msg, 1, System.currentTimeMillis(), routingKey);
        return sendMsg(message);
    }

    /**
     * 回调处理
     *
     * @param correlationDataId
     */
    protected abstract void changeStatus(String correlationDataId);

    private boolean sendMsg(Message inputMessage) {
        String id = UUID.randomUUID().toString().replaceAll("-", "");
        boolean isSuccess;
        try {
            // //重置消息id
            inputMessage.setId(id);
            //存入redis中
//            baseRedisDao.zadd(ERedisCacheKey.KEY_RABBIT_MSG_CACHE.getCode(),Double.parseDouble(String.valueOf(System.currentTimeMillis())),
//                    id,0); //保存消息编号
//            baseRedisDao.saveOrUpdate(ERedisCacheKey.KEY_RABBIT_ROUTING_KEY.getCode()+id,inputMessage.getRoutingKey()); //保存消息类型，以routingKey作为标志
//            baseRedisDao.saveOrUpdate(ERedisCacheKey.KEY_RABBIT_MSG_CONTENT_CACHE.getCode()+id,inputMessage); //保存消息主体内容
            rabbitTemplate.convertAndSend(inputMessage.getRoutingKey(), inputMessage.getMsg(), new CorrelationData(id));
            isSuccess = true;
        } catch (Exception e) {
            System.err.println("发送消息异常id:" + id);
            System.err.println(e);
            isSuccess = false;
        }
        return isSuccess;
    }

    public static class Message {
        /**
         * uuid
         */
        private String id;
        /**
         * 消息内容
         */
        private Object msg;
        /**
         * 已发送次数
         */
        private Integer count;
        /**
         * 有效期
         */
        private Long time;
        /**
         * routingKey
         */
        private String routingKey;

        public String getRoutingKey() {
            return routingKey;
        }

        public void setRoutingKey(String routingKey) {
            this.routingKey = routingKey;
        }

        public Message() {
        }

        public Message(String id, Object msg, Integer count, Long time, String routingKey) {
            this.id = id;
            this.msg = msg;
            this.count = count;
            this.time = time;
            this.routingKey = routingKey;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public Object getMsg() {
            return msg;
        }

        public void setMsg(Object msg) {
            this.msg = msg;
        }

        public Integer getCount() {
            return count;
        }

        public void setCount(Integer count) {
            this.count = count;
        }

        public Long getTime() {
            return time;
        }

        public void setTime(Long time) {
            this.time = time;
        }
    }
}
